﻿using Microsoft.Data.Entity;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace SharpErp.Data.Common.Context
{
    public class LocalSettingContext : DbContext
    {
        public DbSet<Entity.KVEntity> KVEntities { get; set; }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            optionsBuilder.UseSqlite("Filename=" + System.Environment.CurrentDirectory + "\\settings.db3");
            base.OnConfiguring(optionsBuilder);
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);
        }

        public IQueryable<T> All<T>(DbSet<T> dbSet) where T : Common.Entity.BaseEntity
        {
            return dbSet.Where(p => (p.SystemFlag & Common.Entity.BaseEntity.SYS_FLAG_DELETE) == 0);
        }

        public T[] AllArray<T>(DbSet<T> dbSet) where T : Common.Entity.BaseEntity
        {
            return dbSet.Where(p => (p.SystemFlag & Common.Entity.BaseEntity.SYS_FLAG_DELETE) == 0).ToArray<T>();
        }

        public T SelectOne<T>(DbSet<T> dbSet, Expression<Func<T, bool>> predicate) where T : Common.Entity.BaseEntity
        {
            return All<T>(dbSet).FirstOrDefault(predicate);
        }

        public T[] SelectAll<T>(DbSet<T> dbSet, Expression<Func<T, bool>> predicate) where T : Common.Entity.BaseEntity
        {
            return All<T>(dbSet).Where(predicate).ToArray<T>();
        }

        public void Delete<T>(DbSet<T> dbSet, Expression<Func<T, bool>> predicate) where T : Common.Entity.BaseEntity
        {
            var array = All<T>(dbSet).Where(predicate).ToArray<T>();
            foreach (var item in array)
            {
                item.SystemFlag = item.SystemFlag | Common.Entity.BaseEntity.SYS_FLAG_DELETE;
            }
            this.SaveChanges();
        }

        public T Add<T>(DbSet<T> dbSet, T data) where T : Common.Entity.BaseEntity
        {
            data.CreateTime = data.LastModifyTime = DateTime.Now;
            var result = dbSet.Add(data);
            this.SaveChanges();
            return result.Entity;
        }

        public void Update<T>(DbSet<T> dbSet, T data) where T : Common.Entity.BaseEntity
        {
            data.LastModifyTime = DateTime.Now;
            dbSet.Update(data);
            this.SaveChanges();
        }

        public void Clear<T>(DbSet<T> dbSet, Expression<Func<T, bool>> predicate) where T : Common.Entity.BaseEntity
        {
            var array = dbSet.Where(predicate).ToArray<T>();
            dbSet.RemoveRange(array);
            this.SaveChanges();
        }

        public System.Collections.Generic.List<T> GetAllKvItemClass<T>(string key)
        {
            var entity = this.SelectOne(this.KVEntities, p => p.Key.Equals(key));
            return entity == null ? new System.Collections.Generic.List<T>() :
            SharpErp.Data.Util.SerializerManager.GetInstance().GetJSSerializer().Deserialize<System.Collections.Generic.List<T>>(entity.Value);
        }

        public void SetAllKvItemClass<T>(System.Collections.Generic.List<T> list, string key)
        {
            var entity = this.SelectOne(this.KVEntities, p => p.Key.Equals(key)) ??
                  new SharpErp.Data.Common.Entity.KVEntity { CreateTime = new DateTime() };
            entity.LastModifyTime = new DateTime();
            entity.Key = key;
            entity.Value = Util.SerializerManager.GetInstance().GetJSSerializer().Serialize<System.Collections.Generic.List<T>>(list);
            if (entity.Id > 0)
            {
                this.Update<Common.Entity.KVEntity>(this.KVEntities, entity);
            }
            else
            {
                this.Add<Common.Entity.KVEntity>(this.KVEntities, entity);
            }
        }

        public List<Entity.LocalSettingItem> GetSysLocalSettingItem()
        {
            var items = GetAllKvItemClass<Entity.LocalSettingItem>(Entity.LocalSettingItem.KEY_LOCAL_SETTING_ITEM);
            if (items == null || items.Count <= 0) return items;
            return items.Where(p => (p.SystemFlag & Entity.BaseEntity.SYS_FLAG_DELETE) == 0).ToList();
        }

        public void SaveLocalSettingItem(Entity.LocalSettingItem item)
        {
            var items = GetAllKvItemClass<Entity.LocalSettingItem>(Entity.LocalSettingItem.KEY_LOCAL_SETTING_ITEM);
            if (items == null) items = new List<Entity.LocalSettingItem>();
            if (item.Id <= 0)
            {
                item.Id = items.Count > 0 ? items.Max(p => p.Id) + 1 : 1;
                items.Add(item);
            }
            else
            {
                var oldItem = items.Find(p => p.Id == item.Id);
                oldItem.Name = item.Name;
                oldItem.Value = item.Value;
                oldItem.ParentId = item.ParentId;
                oldItem.LastModifyTime = new DateTime();
                oldItem.SetId = item.SetId;
                oldItem.SetShare = item.SetShare;
                oldItem.SystemFlag = item.SystemFlag;
            }
            SetAllKvItemClass<Entity.LocalSettingItem>(items, Entity.LocalSettingItem.KEY_LOCAL_SETTING_ITEM);
        }

        public void DeleteLocalSettingItem(int id)
        {
            var items = GetAllKvItemClass<Entity.LocalSettingItem>(Entity.LocalSettingItem.KEY_LOCAL_SETTING_ITEM);
            if (items == null) return;
            var item = items.Find(p => p.Id == id);
            item.SystemFlag |= Entity.BaseEntity.SYS_FLAG_DELETE;
            SetAllKvItemClass(items, Entity.LocalSettingItem.KEY_LOCAL_SETTING_ITEM);
        }

    }
}
